package com.psm.utilities;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.exceptions.InvalidPasswordException;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdfwriter.COSWriter;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.PDFMergerUtility;
import org.apache.pdfbox.util.Splitter;

public class PDFUtilities
{
    public static void splitPageByPage(Map< String, String > args) throws Exception
    {
	String[] strArgs =
	{ args.get( "filename" ) };
	split_byPage( strArgs );
    }

    public static void extractPageRange(Map< String, String > config, String filename) throws Exception
    {
	String[] strArgs =
	{ "-split", config.get( "split" ), "-startPage", config.get( "startPage" ), "-endPage", config.get( "endPage" ), filename };
	split_byRange( strArgs );
    }

    /*
     * public static void testPDFSplit(String filename, String split, String
     * startPage, String endPage) throws Exception { String[] strArgs = {
     * "-split", split, "-startPage", startPage, "-endPage", endPage, filename
     * }; PDFSplit.main( strArgs ); }
     * 
     * public static void testPDFSplit(String filename, String split, String
     * startPage) throws Exception { String[] strArgs = { "-split", split,
     * "-startPage", startPage, filename }; PDFSplit.main( strArgs ); }
     * 
     * public static void testPDFSplit(String filename, String split) throws
     * Exception { String[] strArgs = { "-split", split, filename };
     * PDFSplit.main( strArgs ); }
     */

    private static void split_byPage(String[] args) throws Exception
    {
	String password = "";
	String split = "1";

	Splitter splitter = new Splitter();
	String pdfFile = null;
	for ( int i = 0; i < args.length; i++ )
	{
	    if ( args[i].equals( "-password" ) )
	    {
		i++;
		if ( i >= args.length )
		{
		    usage();
		}
		password = args[i];
	    }
	    else if ( args[i].equals( "-split" ) )
	    {
		i++;
		if ( i >= args.length )
		{
		    usage();
		}
		split = args[i];
	    }
	    else
	    {
		if ( pdfFile != null )
		    continue;
		pdfFile = args[i];
	    }

	}

	if ( pdfFile == null )
	{
	    usage();
	}
	else
	{
	    InputStream input = null;
	    PDDocument document = null;
	    List< PDDocument > documents = null;
	    try
	    {
		input = new FileInputStream( pdfFile );
		document = parseDocument( input );

		if ( document.isEncrypted() )
		{
		    try
		    {
			document.decrypt( password );
		    }
		    catch ( InvalidPasswordException e )
		    {
			if ( args.length == 4 )
			{
			    System.err.println( "Error: The supplied password is incorrect." );
			    System.exit( 2 );
			}
			else
			{
			    System.err.println( "Error: The document is encrypted." );
			    usage();
			}
		    }
		}

		splitter.setSplitAtPage( Integer.parseInt( split ) );
		documents = splitter.split( document );
		for ( int i = 0; i < documents.size(); i++ )
		{
		    PDDocument doc = (PDDocument) documents.get( i );
		    String fileName = pdfFile.substring( 0, pdfFile.length() - 4 ) + "-" + (i + 1) + ".pdf";
		    writeDocument( doc, fileName );
		    doc.close();
		}
	    }
	    finally
	    {
		int i;
		PDDocument doc;
		if ( input != null )
		{
		    input.close();
		}
		if ( document != null )
		{
		    document.close();
		}
		for ( i = 0; (documents != null) && (i < documents.size()); i++ )
		{
		    doc = (PDDocument) documents.get( i );
		    doc.close();
		}
	    }
	}
    }

    private static void split_byRange(String[] args) throws Exception
    {
	String password = "";
	String split = "1";
	int startPage = 1;
	int endPage = 1;

	Splitter splitter = new Splitter();
	String pdfFile = null;
	for ( int i = 0; i < args.length; i++ )
	{
	    if ( args[i].equals( "-password" ) )
	    {
		i++;
		if ( i >= args.length )
		{
		    usage();
		}
		password = args[i];
	    }
	    else if ( args[i].equals( "-split" ) )
	    {
		i++;
		if ( i >= args.length )
		{
		    usage();
		}
		if ( args[i] != null )
		{
		    split = args[i];
		}
	    }
	    else if ( args[i].equals( "-startPage" ) )
	    {
		i++;
		if ( i >= args.length )
		{
		    usage();
		}
		startPage = Integer.parseInt( args[i] );
	    }
	    else if ( args[i].equals( "-endPage" ) )
	    {
		i++;
		if ( i >= args.length )
		{
		    usage();
		}
		endPage = Integer.parseInt( args[i] );
	    }
	    else
	    {
		if ( pdfFile != null )
		    continue;
		pdfFile = args[i];
	    }

	}

	if ( pdfFile == null )
	{
	    usage();
	}
	else
	{
	    InputStream input = null;
	    PDDocument document = null;
	    List< PDDocument > documents = null;
	    try
	    {
		input = new FileInputStream( pdfFile );
		document = parseDocument( input );

		if ( document.isEncrypted() )
		{
		    try
		    {
			document.decrypt( password );
		    }
		    catch ( InvalidPasswordException e )
		    {
			if ( args.length == 4 )
			{
			    System.err.println( "Error: The supplied password is incorrect." );
			    System.exit( 2 );
			}
			else
			{
			    System.err.println( "Error: The document is encrypted." );
			    usage();
			}
		    }
		}

		splitter.setSplitAtPage( Integer.parseInt( split ) );
		documents = splitter.split( document );
		List< String > tempDocs = new ArrayList< String >();
		for ( int i = startPage - 1; i < endPage; i++ )
		{
		    PDDocument doc = (PDDocument) documents.get( i );
		    String fileName = pdfFile.substring( 0, pdfFile.length() - 4 ) + "-" + (i + 1) + ".pdf";
		    tempDocs.add( fileName );
		    writeDocument( doc, fileName );
		    doc.close();
		}
		PDFMergerUtility merger = new PDFMergerUtility();
		String sourceFileName = "";
		for ( int i = 0; i < tempDocs.size(); i++ )
		{
		    sourceFileName = tempDocs.get( i );
		    merger.addSource( sourceFileName );
		}
		String destinationFileName = pdfFile.substring( 0, pdfFile.length() - 4 ) + "_Pages_" + startPage + "-" + endPage + ".pdf";
		merger.setDestinationFileName( destinationFileName );
		merger.mergeDocuments();
		for ( int i = 0; i <= endPage - startPage; i++ )
		{
		    File f = new File( tempDocs.get( i ) );
		    f.delete();
		}

	    }
	    finally
	    {
		int i;
		PDDocument doc;
		if ( input != null )
		{
		    input.close();
		}
		if ( document != null )
		{
		    document.close();
		}
		for ( i = 0; (documents != null) && (i < documents.size()); i++ )
		{
		    doc = (PDDocument) documents.get( i );
		    doc.close();
		}
	    }
	}
    }

    private static final void writeDocument(PDDocument doc, String fileName) throws IOException, COSVisitorException
    {
	FileOutputStream output = null;
	COSWriter writer = null;
	try
	{
	    output = new FileOutputStream( fileName );
	    writer = new COSWriter( output );
	    writer.write( doc );
	}
	finally
	{
	    if ( output != null )
	    {
		output.close();
	    }
	    if ( writer != null )
	    {
		writer.close();
	    }
	}
    }

    private static PDDocument parseDocument(InputStream input) throws IOException
    {
	PDFParser parser = new PDFParser( input );
	parser.parse();
	return parser.getPDDocument();
    }

    private static void usage()
    {
	System.err
		.println( "Usage: java -jar pdfbox-app-x.y.z.jar PDFSplit [OPTIONS] <PDF file>\n  -password  <password>        Password to decrypt document\n  -split     <integer>         split after this many pages\n  <PDF file>                   The PDF document to use\n" );

	System.exit( 1 );
    }
}
